/*

This file is part of roomyak.

Copyright (C) 2008 Pixecur Technologies Incorporated (Esotera).
Visit Esotera at http://www.esoteras3.com
 
roomyak is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
 
roomyak is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.
 
You should have received a copy of the GNU General Public License
along with roomyak; see the file COPYING.  If not, write to 
Pixecur Technologies, 213-31 Peet Street, St. John's, NL, A1B 3W8. 
 
Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
 
*/

package com.datasentinel.os.windows;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.Icon;
import javax.swing.filechooser.FileSystemView;

import com.datasentinel.os.OSToolKit;
import com.datasentinel.os.ProcessIterator;
import com.datasentinel.util.win32.Win32Helper;

public class WindowsOSToolKit extends OSToolKit
{

	private static Logger logger = Logger.getLogger(WindowsOSToolKit.class.getName());

	
//	private static final Set<String> vistaMediaExtensionSet = new HashSet<String>();
//	static{
//		vistaMediaExtensionSet.add("dvr-ms");
//		vistaMediaExtensionSet.add("wmv");
//		vistaMediaExtensionSet.add("mpg");
//		vistaMediaExtensionSet.add("asf");
//	}
//	
	
	public ProcessIterator exec(File dir, String command, String args) throws Exception
	{
		Process process = null;
		String[] commands;
		if (args == null || args.length() == 0)
		{
			if(process == null)
			{
				commands = new String[]{"rundll32", "url.dll,FileProtocolHandler", 
					 toURI(dir, command).toString()};
				process = Runtime.getRuntime().exec(commands, null, dir);
			}
		}
		else
		{
			process = Runtime.getRuntime().exec(command + " " + args, null, dir);
		}

		return new ProcessIterator(process); 
	}
	
	public void execAndForget(File workingDirectory, String command, String arguments) throws Exception
	{
		execAndForget(workingDirectory, command, arguments == null ? null : new String[]{arguments});
	}
	
	public void execAndForget(File workingDirectory, String command, String[] arguments)
	throws Exception
	{
		
		StringBuffer argumentsBuffer = new StringBuffer();
		if(arguments != null)
		{
			for(String argument: arguments)
			{
				if(argument != null && argument.length() > 0)
				{
					argumentsBuffer.append(" ");
					argumentsBuffer.append("\"").append(argument).append("\"");
				}
			}
		}
		Win32Helper.executeCommand(command, workingDirectory, argumentsBuffer.toString());
	}
	
	public void makeLink(File link, File file) throws IOException
	{
		// A NTFS 5.0 hard link, if possible, is better than a short-cut
		String cmds[] = null;
		if (os.indexOf("xp") >= 0)
			cmds = new String[]{"fsutil","hardlink", "create", link.getAbsolutePath(), file.getAbsolutePath()};
		else if (os.indexOf("windows") >= 0)
			cmds = new String[]{"cmd", "/c", "start", "/b", "mklink", link.isDirectory()?"/J":"/H", "\"" + link.getAbsolutePath() + "\"", "\"" + file.getAbsolutePath() + "\""};
		else
		{
			throw new IOException("cannot perform file link");
		}
		try
		{
			if (cmds != null)
				exec(cmds).exitValue();
		}
		catch (InterruptedException e)
		{
			System.out.println(e);
		}
	}
    public String getTempDirDefault()
	{
		return "c:\\temp\\Pixecur";
	}
	public boolean isWindows()
	{
		return true;
	}
	public ArrayList<String> getMacAddresses(ArrayList<String> macs) throws IOException
	{
		for (Iterator<String> i = exec(new String[]{"ipconfig", "/all"}); i.hasNext();)
		{
			String line = i.next();
			if (line.indexOf("Physical Address")>=0)
			{
				line = line.substring(line.lastIndexOf(":") + 1).trim();
				if (new StringTokenizer(line, "-").countTokens() == 6)
					macs.add(line.toUpperCase());
			}				
		}
//		macs.add("00-17-3F-B1-EB-30");?
		return macs;
	}
	public boolean isProcessRunning(String processName, boolean killProcess) throws IOException
	{
		try{
			ProcessIterator i = null;
			if (killProcess)
			{
				
				not_killed: for(int r = 0; r < 4; ++r)
				{
						
					for (i = exec(new String[]{"taskkill", "/F", "/IM", processName}); i.hasNext(); )
					{
						String line = i.next();
						if (line.toLowerCase().indexOf("success") >= 0)
							break;
					}
					i.close();
					
					for (i = exec(new String[]{"tasklist", "/FO", "LIST"}); i.hasNext(); )
						if (i.next().toLowerCase().indexOf(processName.toLowerCase()) >= 0)
						{
							i.close();
							continue not_killed;
						}
					
					return false;
				}						
				return true;
			}
			else
			{
				for (i = exec(new String[]{"tasklist", "/FO", "LIST"}); i.hasNext(); )
					if (i.next().toLowerCase().indexOf(processName.toLowerCase()) >= 0)
					{
						i.close();
						return true;
					}
			}
		}
		catch(Exception e)
		{
			logger.log(Level.SEVERE, "Unable to kill the process: " + processName, e);
		}
		return false;
	}
	@Override
	public long getProcessId() throws IOException
	{
		return Win32Helper.getCurrentProcessId();
	}
	@Override
	public long getProcessId(String processSpecifier) throws IOException
	{
		throw new IOException(" getProcessId() method not implemented for this OS.");
	}
	@Override
	public boolean killProcess(long processId) throws IOException
	{
		throw new IOException(" killProcess() method not implemented for this OS.");
	}

	
	private static final Map<String, Icon> systemIconCache = new HashMap<String, Icon>();
	
	public synchronized Icon getFileIcon(String name)
	{
		if(name == null)
			return ICON_FILE;
		
		String extension = null;
		
		int semicolonIndex = name.indexOf(';');
		if(semicolonIndex >= 0)
			name = name.substring(0, semicolonIndex);
		File file = new File(name);
		name = file.getName();
		int dotIndex = name.indexOf('.');
		if(dotIndex>=0)
			extension = name.substring(dotIndex + 1);
		
		if(extension != null && systemIconCache.containsKey(extension))
			return systemIconCache.get(extension);
		
		Icon fileIcon = null;
		try
		{
			File testFile = File.createTempFile("px_tmp_ico", "." + extension);
			fileIcon = FileSystemView.getFileSystemView().getSystemIcon(testFile);
			testFile.delete();
		}
		catch (IOException e)
		{}
		
		if(fileIcon == null)
			return ICON_FILE;
		
		systemIconCache.put(extension, fileIcon);
		return fileIcon;
	}
	
	public boolean setProcessPriorityBelowNormal()
	{
		return Win32Helper.setProcessPriorityBelowNormal();
	}

	public boolean setProcessPriorityNormal()
	{
		return Win32Helper.setProcessPriorityNormal();
	}
}

